<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .container {
            display: flex;
            height: 100vh;
            /*background-color: ;*/
        }

    </style>
</head>
<body onload="init()">
<div id="myDiagramDiv" class="container"></div>
<script src="release/go.js"></script>
<script>
    function init() {
        if (window.goSamples) goSamples();  // init for these samples -- you don't need to call this
        var $ = go.GraphObject.make;  // for more concise visual tree definitions
        var nodes = null;
        myDiagram =
            $(go.Diagram, "myDiagramDiv",
                {
                    "grid.visible": true,
//                    allowMove: false,
//                    allowCopy: false,
                    allowDelete: false,
                    allowHorizontalScroll: false,
                    "grid.gridCellSize": new go.Size(30, 20),
                    "draggingTool.isGridSnapEnabled": true,//根据网格尺寸移动
                    "resizingTool.isGridSnapEnabled": true,
                    "rotatingTool.snapAngleMultiple": 90,
                    "rotatingTool.snapAngleEpsilon": 45,
                    "undoManager.isEnabled": true
                });

        // when the document is modified, add a "*" to the title and enable the "Save" button
        myDiagram.addDiagramListener("Modified", function (e) {
            var button = document.getElementById("SaveButton");
            if (button) button.disabled = !myDiagram.isModified;
            var idx = document.title.indexOf("*");
            if (myDiagram.isModified) {
                if (idx < 0) document.title += "*";
            } else {
                if (idx >= 0) document.title = document.title.substr(0, idx);
            }
        });

        myDiagram.nodeTemplateMap.add("Process",
            $(go.Node, "Auto",
                {
                    locationSpot: new go.Spot(0.5, 0.5), locationObjectName: "SHAPE",
                    resizable: true, resizeObjectName: "SHAPE"
                },
                new go.Binding("location", "pos", go.Point.parse).makeTwoWay(go.Point.stringify),
                $(go.Shape, "Cylinder1",
                    {
                        name: "SHAPE",
                        strokeWidth: 2,
                        fill: $(go.Brush, "Linear",
                            {
                                start: go.Spot.Left, end: go.Spot.Right,
                                0: "gray", 0.5: "white", 1: "gray"
                            }),
                        minSize: new go.Size(50, 50),
                        portId: "", fromSpot: go.Spot.AllSides, toSpot: go.Spot.AllSides
                    },
                    new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify)),
                $(go.TextBlock,
                    {
                        alignment: go.Spot.Center, textAlign: "center", margin: 5,
                        editable: true
                    },
                    new go.Binding("text").makeTwoWay())
            ));

        myDiagram.nodeTemplateMap.add("Valve",
            $(go.Node, "Vertical",
                {
                    locationSpot: new go.Spot(0.5, 1, 0, -21), locationObjectName: "SHAPE",
                    selectionObjectName: "SHAPE", rotatable: true
                },
                new go.Binding("angle").makeTwoWay(),
                new go.Binding("location", "pos", go.Point.parse).makeTwoWay(go.Point.stringify),
                $(go.TextBlock,
                    {alignment: go.Spot.Center, textAlign: "center", margin: 5, editable: true},
                    new go.Binding("text").makeTwoWay(),
                    // keep the text upright, even when the whole node has been rotated upside down
                    new go.Binding("angle", "angle", function (a) {
                        return a === 180 ? 180 : 0;
                    }).ofObject()
                ),
                $(go.Shape,
                    {
                        name: "SHAPE",
                        geometryString: "F1 M0 0 L40 20 40 0 0 20z M20 10 L20 30 M12 30 L28 30",
                        strokeWidth: 2,
                        fill: $(go.Brush, "Linear", {0: "gray", 0.35: "white", 0.7: "gray"}),
                        portId: "", fromSpot: new go.Spot(1, 0.35), toSpot: new go.Spot(0, 0.35)
                    })
            ));

        myDiagram.linkTemplate =
            $(go.Link,
                {routing: go.Link.AvoidsNodes, curve: go.Link.JumpGap, corner: 10, reshapable: true, toShortLength: 7},
                new go.Binding("points").makeTwoWay(),
                // mark each Shape to get the link geometry with isPanelMain: true
                $(go.Shape, {isPanelMain: true, stroke: "black", strokeWidth: 5}),
                $(go.Shape, {isPanelMain: true, stroke: "gray", strokeWidth: 3}),
                $(go.Shape, {
                    isPanelMain: true,
                    stroke: "white",
                    strokeWidth: 1,
                    name: "PIPE",
                    strokeDashArray: [10, 10]
                }),
                $(go.Shape, {toArrow: "Triangle", fill: "black", stroke: null})
            );

        load();

        loop();  // animate some flow through the pipes
    }

    function loop() {
        var diagram = myDiagram;
        setTimeout(function () {
            var oldskips = diagram.skipsUndoManager;
            diagram.skipsUndoManager = true;
            diagram.links.each(function (link) {
                var shape = link.findObject("PIPE");
                var off = shape.strokeDashOffset - 2;
                shape.strokeDashOffset = (off <= 0) ? 20 : off;
            });
            diagram.skipsUndoManager = oldskips;
            loop();
        }, 100);
    }
    function save() {
        nodes = myDiagram.model.toJson();
        myDiagram.isModified = false;
    }
    function load() {
        var nodes = {
            "class": "go.GraphLinksModel",
            "nodeDataArray": [
                {"key": "P1", "category": "Process", "pos": "150 120", "text": "Process"},
                {"key": "P2", "category": "Process", "pos": "330 320", "text": "Tank"},
                {"key": "V1", "category": "Valve", "pos": "270 120", "text": "V1"},
                {"key": "P3", "category": "Process", "pos": "150 420", "text": "Pump"},
                {"key": "V2", "category": "Valve", "pos": "150 280", "text": "VM", "angle": 270},
                {"key": "V3", "category": "Valve", "pos": "270 420", "text": "V2", "angle": 180},
                {"key": "P4", "category": "Process", "pos": "450 140", "text": "Reserve Tank"},
                {"key": "V4", "category": "Valve", "pos": "390 60", "text": "VA"},
                {"key": "V5", "category": "Valve", "pos": "450 260", "text": "VB", "angle": 90}
            ],
            "linkDataArray": [
                {"from": "P1", "to": "V1"},
                {"from": "P3", "to": "V2"},
                {"from": "V2", "to": "P1"},
                {"from": "P2", "to": "V3"},
                {"from": "V3", "to": "P3"},
                {"from": "V1", "to": "V4"},
                {"from": "V4", "to": "P4"},
                {"from": "V1", "to": "P2"},
                {"from": "P4", "to": "V5"},
                {"from": "V5", "to": "P2"}
            ]
        }
        myDiagram.model = go.Model.fromJson(nodes);
    }
</script>
</body>
</html>